" vim:ft=vim
" Test writing functionality.

"
" write() family
"

Before;
let write_family = ['write', 'writeline', 'writelines']
let files = map(range(2), 'tempname()')
call map(copy(files), 'writefile([], v:val)')


Execute(Write mode creates non-existing file);
let file = tempname()
Assert !filewritable(file)
let f = object#open(file, 'w')
call f.close()
Assert filewritable(file)

Execute(a single call to write(str) writes a _line_ to f);
let t = files[0]
let f = object#open(t, 'w')

call f.write('aaa')
call f.close()
AssertEqual 'aaa', readfile(t)[0]


Execute(write() concats to the current line of f);
let t = files[0]
let f = object#open(t, 'w')
let data = [ 'This ', 'is ', 'an ', 'apple.' ]

call map(copy(data), 'f.write(v:val)')
call f.close()
AssertEqual join(data, ''), readfile(t)[0]


Execute(multiple writeline()'s is equal to a single writelines());
let data = split(repeat('a', 10), '')

" Take 2 empty tempfiles.
let files = files[0:1]

" Open all the tempfiles.
let targets = map(copy(files), 'object#open(v:val, "w")')

" Here is the difference
call targets[0].writelines(data)
for x in data
  call targets[1].writeline(x)
endfor

" Verify the results.
call map(targets, 'v:val.close()')
let results = map(copy(files), 'readfile(v:val)')
AssertEqual results[0], results[1]

"
" Throwing behaviours of write() and friends.
"
Execute(write()/writeline() throws WrongType for non-String);
let f = object#open(files[0], 'w')

for x in write_family[:1]
  AssertThrows call call(g:f[g:x], [1])
  Log g:vader_exception
  Assert g:vader_exception =~# 'WrongType'
endfor


Execute(writelines throws WrongType for iter that returns non-String);
AssertThrows call object#open(g:files[0], 'w').writelines(range(10))
Log g:vader_exception
Assert g:vader_exception =~# 'WrongType'


Execute(writelines() throws TypeError for non-iterable input);
let f = object#open(files[0], 'w')
AssertThrows call g:f.writelines(1)
Assert g:vader_exception =~# 'TypeError'


Execute(Although open()'ed writable, f.write() and friends throw OSError if f becomes unwritable);
let t = files[0]
Assert filewritable(t)

let f = object#open(t, 'w')
call setfperm(t, 'r--------')

for x in write_family
  AssertThrows call g:f[g:x]('aaa')
  Assert g:vader_exception =~# 'OSError'
endfor


Execute(Throws OSError if write operations are not supported by the mode);
let f = object#open(files[0])
for x in write_family
  AssertThrows call g:f[g:x]('')
  Log g:vader_exception
  Assert g:vader_exception =~# 'OSError'
endfor


After;
call map(files, 'delete(v:val)')
